1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 import java.lang.management.ManagementFactory;
36 import java.lang.reflect.Method;
37 import java.util.Arrays;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.Map;
41 import java.util.Set;
42 import java.util.logging.Logger;
43 import javax.management.Descriptor;
44 import javax.management.MBeanInfo;
45 import javax.management.MBeanOperationInfo;
46 import javax.management.MBeanServer;
47 import javax.management.ObjectName;
48 import javax.management.StandardMBean;
49 import javax.management.openmbean.OpenMBeanOperationInfo;
50
51
52
53
54
55 public class TooManyFooTest {
56
57
58
59
60 private static final Logger LOG =
61 Logger.getLogger(TooManyFooTest.class.getName());
62
63 public static class NumberHolder {
64 public Integer getNumber() { return 0;}
65 public void setNumber(Integer n) {};
66 }
67 public static class MyNumberHolder extends NumberHolder {
68
69 }
70 public interface Parent1 {
71 public int foo();
72 public Integer barfoo();
73 public Long foobar();
74
75 public Number toofoo();
76
77 public Object toofoofoo();
78 public NumberHolder toobarbar();
79 }
80
81 public interface Parent2 {
82 public int foo();
83 public Number barfoo();
84 public Number foobar();
85 public Object toofoo();
86 public NumberHolder toofoofoo();
87 public Object toobarbar();
88 }
89
90 public interface ChildMBean extends Parent1, Parent2 {
91 public Long foobar();
92 public Long toofoo();
93 }
94
95 public interface ChildMXBean extends Parent1, Parent2 {
96 public Long foobar();
97 public Long toofoo();
98 }
99
100 public interface ChildMixMXBean extends ChildMBean, ChildMXBean {
101 }
102
103 public static class Child implements ChildMBean {
104 public int foo() {return 0;}
105 public Long foobar() {return 0L;}
106 public Long toofoo() {return 0L;}
107 public Integer barfoo() {return 0;}
108 public MyNumberHolder toofoofoo() { return null;}
109 public MyNumberHolder toobarbar() { return null;}
110 }
111
112 public static class ChildMix implements ChildMXBean {
113 public int foo() {return 0;}
114 public Long foobar() {return 0L;}
115 public Long toofoo() {return 0L;}
116 public Integer barfoo() {return 0;}
117 public MyNumberHolder toofoofoo() { return null;}
118 public MyNumberHolder toobarbar() { return null;}
119 }
120
121 public static class ChildMixMix extends Child implements ChildMixMXBean {
122 }
123
124
125
126 public TooManyFooTest() {
127 }
128
129 private static final int OPCOUNT;
130 private static final Map<String,String> EXPECTED_TYPES;
131 private static final String[][] type_array = {
132 { "foo", int.class.getName() },
133 { "foobar", Long.class.getName()},
134 { "toofoo", Long.class.getName()},
135 { "barfoo", Integer.class.getName()},
136 { "toofoofoo", NumberHolder.class.getName()},
137 { "toobarbar", NumberHolder.class.getName()},
138 };
139 static {
140 try {
141 final Set<String> declared = new HashSet<String>();
142 for (Method m:Child.class.getDeclaredMethods()) {
143 declared.add(m.getName()+Arrays.asList(m.getParameterTypes()));
144 }
145 final Set<String> exposed = new HashSet<String>();
146 for (Method m:ChildMBean.class.getMethods()) {
147 exposed.add(m.getName()+Arrays.asList(m.getParameterTypes()));
148 }
149 declared.retainAll(exposed);
150 OPCOUNT = declared.size();
151 EXPECTED_TYPES = new HashMap<String,String>();
152 for (String[] st:type_array) {
153 EXPECTED_TYPES.put(st[0],st[1]);
154 }
155 } catch (Exception x) {
156 throw new ExceptionInInitializerError(x);
157 }
158 }
159
160 private static void test(Object child, String name, boolean mxbean)
161 throws Exception {
162 final ObjectName childName =
163 new ObjectName("test:type=Child,name="+name);
164 final MBeanServer server =
165 ManagementFactory.getPlatformMBeanServer();
166 server.registerMBean(child,childName);
167 try {
168 final MBeanInfo info = server.getMBeanInfo(childName);
169 System.out.println(name+": " + info.getDescriptor());
170 final int len = info.getOperations().length;
171 if (len == OPCOUNT) {
172 System.out.println(name+": OK, only "+OPCOUNT+
173 " operations here...");
174 } else {
175 final String qual = (len>OPCOUNT)?"many":"few";
176 System.err.println(name+": Too "+qual+" foos! Found "+
177 len+", expected "+OPCOUNT);
178 for (MBeanOperationInfo op : info.getOperations()) {
179 System.err.println("public "+op.getReturnType()+" "+
180 op.getName()+"();");
181 }
182 throw new RuntimeException("Too " + qual +
183 " foos for "+name);
184 }
185
186 final Descriptor d = info.getDescriptor();
187 final String mxstr = String.valueOf(d.getFieldValue("mxbean"));
188 final boolean mxb =
189 (mxstr==null)?false:Boolean.valueOf(mxstr).booleanValue();
190 System.out.println(name+": mxbean="+mxb);
191 if (mxbean && !mxb)
192 throw new AssertionError("MXBean is not OpenMBean?");
193
194 for (MBeanOperationInfo mboi : info.getOperations()) {
195
196
197 if (mxbean && !mboi.getName().equals("foo")) {
198
199
200
201
202
203
204 if (!(mboi instanceof OpenMBeanOperationInfo))
205 throw new AssertionError("Operation "+mboi.getName()+
206 "() is not Open?");
207 }
208
209 final String exp = EXPECTED_TYPES.get(mboi.getName());
210
211
212
213
214 String type = (String)mboi.getDescriptor().
215 getFieldValue("originalType");
216 if (type == null) type = mboi.getReturnType();
217 if (type.equals(exp)) continue;
218 System.err.println("Bad return type for "+
219 mboi.getName()+"! Found "+type+
220 ", expected "+exp);
221 throw new RuntimeException("Bad return type for "+
222 mboi.getName());
223 }
224 } finally {
225 server.unregisterMBean(childName);
226 }
227 }
228
229 public static void main(String[] args) throws Exception {
230 final Child child = new Child();
231 test(child,"Child[MBean]",false);
232 final ChildMix childx = new ChildMix();
233 test(childx,"ChildMix[MXBean]",true);
234 final ChildMixMix childmx = new ChildMixMix();
235 test(childmx,"ChildMixMix[MXBean]",false);
236 final StandardMBean schild = new StandardMBean(child,ChildMBean.class);
237 test(schild,"Child[StandarMBean(Child)]",false);
238 final StandardMBean schildx =
239 new StandardMBean(childx,ChildMXBean.class,true);
240 test(schildx,"ChildMix[StandarMXBean(ChildMix)]",true);
241 final StandardMBean schildmx =
242 new StandardMBean(childmx,ChildMixMXBean.class,true);
243 test(schildmx,"ChildMixMix[StandarMXBean(ChildMixMix)]",true);
244 }
245
246 }